package main

import (
	"fmt"
	"reflect"
	"strconv"
	"time"
)

/*
1.整数类型之间可以相互转换

	浮点数和整数之间可以相互转换
	转换时要注意精度损失

2.字符串相关转换：

	字符串和字节切片（[]byte）可以相互转换
	字符串和 rune 切片（[]rune）可以相互转换
	不能直接将字符串转换为数值类型

3.类型转换的安全规则：

	必须显式进行类型转换
	编译器会检查类型转换的合法性
	不兼容的类型转换会导致编译错误

4.最佳实践：

	在进行运算前，确保操作数类型相同
	注意类型转换可能带来的精度损失
	使用 fmt.Printf 的 %T 格式化符号来检查变量类型
*/
func main() {

	numConvert()

	strConvert()

	strConv()

	man := Man{Name: "zjw", age: 32}
	woman := Woman(man)
	println(woman.objConvert())

	timeConvert()
}

func numConvert() {
	var i int32 = 17
	var b byte = 5
	var f float32

	// 数字类型可以直接强转
	f = float32(i) / float32(b)
	fmt.Printf("f 的值为: %f\n", f)

	//下面代码会编译错误，不同类型的变量不能在一起计算
	//	f = float32(i) / float64(b)

	// 当int32类型强转成byte时，高位被直接舍弃
	var i2 int32 = 256
	var b2 byte = byte(i2)
	fmt.Printf("b2 的值为: %d\n", b2)

	// 示例1：整数类型之间的转换
	var j int64 = int64(i)
	fmt.Printf("int32 转 int64: %d\n", j)

	// 示例2：整数和浮点数之间的转换
	f = 3.14
	var k int = int(f) // 会截断小数部分
	fmt.Printf("float32 转 int: %d\n", k)
}

// string 类型、[]byte 类型与[]rune 类型之间可以类似数字类型那样相互转换，并且数据不会有任何丢失。
func strConvert() {

	//字符串转byte，rune
	str := "hello world"
	bytes := []byte(str)
	runes := []rune(str)
	fmt.Printf("bytes 的值为: %v, %c\n", bytes, bytes)
	fmt.Printf("runes 的值为: %v, %c \n", runes, runes)

	//byte，rune转字符串
	str2 := string(bytes)
	str3 := string(runes)
	fmt.Printf("str2 的值为: %v \n", str2)
	fmt.Printf("str3 的值为: %v \n", str3)
}

func strConv() {
	str := "123"
	num, err := strconv.Atoi(str)
	if err != nil {
		panic(err)
	}
	fmt.Printf("字符串转换为int: %d \n", num)
	str1 := strconv.Itoa(num)
	fmt.Printf("int转换为字符串: %s \n", str1)

	ui64, err := strconv.ParseUint(str, 10, 32)
	fmt.Printf("字符串转换为uint64: %d \n", num)

	str2 := strconv.FormatUint(ui64, 2)
	fmt.Printf("uint64转换为字符串: %s \n", str2)
}

// 时间转换
func timeConvert() {
	now := time.Now()
	iso := now.Format("2006/01/02 15:04:05Z07:00")
	fmt.Println("ISO 8601:", iso)
	fmt.Printf("type of iso: %s\n", reflect.TypeOf(iso))
	fmt.Printf("当前时间: %v\n", now)
	fmt.Printf("当前时间类型: %s\n", reflect.TypeOf(now))

	// 解析带时区的时间字符串
	layout := "2006-01-02 15:04:05 -0700"
	str := "2023-10-01 12:30:45 +0800"
	t, err := time.Parse(layout, str)
	if err != nil {
		panic(err)
	}
	fmt.Println("带时区时间:", t)
}

type Man struct {
	Name string
	age  int
}

type Woman struct {
	Name string
	age  int
}

/*
结构体类型之间在一定条件下也可以转换的。
当两个结构体中的字段名称以及类型都完全相同，仅结构体名称不同时，这两个结构体类型即可相互转换。
*/
func (woman *Woman) objConvert() int {
	return woman.age
}
